use actix_web::{error, get, post, put, web, Error, HttpRequest, HttpResponse};
use datasource_connector::restful::{get_class, get_instance, get_instance_by_id, get_instances};
use model_graph_types::{
    datasource::{
        DataSourceProvider, GetDataSourceOptions, QueryCondition, QueryExtention, QueryOptions,
    },
    modeling::system_meta_database,
};
use serde::{Deserialize, Serialize};
use serde_json::json;

#[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct FindRequest {
    conditions: QueryCondition,
    extentions: Option<QueryExtention>,
    options: Option<QueryOptions>,
}

#[post("/ds/findone/{clazz}")]
pub async fn ds_find_one(
    state: web::Data<crate::AppState>,
    identifier_param: web::Path<String>,
    request_obj: web::Json<FindRequest>,
    _req: HttpRequest,
) -> Result<HttpResponse, Error> {
    //
    let context = state.context.clone();
    //用户ID
    // let user_id = crate::services::get_user_id(&req)?;
    //
    let clazz = identifier_param.into_inner();
    let FindRequest {
        conditions,
        extentions,
        options,
    } = request_obj.into_inner();
    let meta_datasource =
        system_meta_database().map_err(|err| error::ErrorInternalServerError(err))?;
    let default_datasource = context
        .get_datasource(GetDataSourceOptions::default())
        .await
        .map_err(|err| error::ErrorInternalServerError(err))?;

    let res = get_instance(
        context,
        &Some(meta_datasource),
        &default_datasource,
        &clazz,
        conditions,
        extentions,
        options,
    )
    .await
    .map_err(|err| error::ErrorInternalServerError(err))?;

    Ok(HttpResponse::Ok().json(json!(res)))
}

#[post("/ds/find/{clazz}")]
pub async fn ds_find(
    state: web::Data<crate::AppState>,
    identifier_param: web::Path<String>,
    request_obj: web::Json<FindRequest>,
    _req: HttpRequest,
) -> Result<HttpResponse, Error> {
    //
    let context = state.context.clone();
    //用户ID
    // let user_id = crate::services::get_user_id(&req)?;
    //
    let clazz = identifier_param.into_inner();
    let FindRequest {
        conditions,
        extentions,
        options,
    } = request_obj.into_inner();

    let meta_datasource =
        system_meta_database().map_err(|err| error::ErrorInternalServerError(err))?;
    let default_datasource = context
        .get_datasource(GetDataSourceOptions::default())
        .await
        .map_err(|err| error::ErrorInternalServerError(err))?;

    let res = get_instances(
        context,
        &Some(meta_datasource),
        &default_datasource,
        &clazz,
        conditions,
        extentions,
        options,
    )
    .await
    .map_err(|err| error::ErrorInternalServerError(err))?;

    Ok(HttpResponse::Ok().json(json!(res)))
}
